package com.ibeeking.found.common.utils;

import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RemoteUtil {
    private static Logger logger = LoggerFactory.getLogger(RemoteUtil.class);

    public static String getByHttpClient(HttpServletRequest req, String url) {
        HttpClient client = new HttpClient();
        GetMethod method = new GetMethod(url);
        method.getParams().setParameter("http.method.retry-handler", new DefaultHttpMethodRetryHandler(3, false));
        method.getParams().setContentCharset("UTF-8");
        method.setRequestHeader("Content-Type", "text/html; charset=UTF-8");
        String cookieValue = req.getHeader("Cookie");
        if (null != req && StringUtils.isNotBlank(cookieValue))
            method.setRequestHeader("Cookie", cookieValue);
        try {
            int statusCode = client.executeMethod((HttpMethod)method);
            if (statusCode != 200)
                return "ERROR:status_code" + statusCode;
            String response = method.getResponseBodyAsString();
            logger.info("[REMOTE GET] URL(" + url + "),COKI(" + cookieValue + "),RET(" + response + ")");
            return response;
        } catch (Exception e) {
            System.out.println("[ERROR] Get URL (" + url + ") error(" + e.getMessage() + ")");
            return "ERROR:" + e.getMessage();
        } finally {
            method.releaseConnection();
        }
    }

    public static String get(String url) {
        return getByHttpClient(null, url);
    }

    public static String get(HttpServletRequest req, String url) {
        return getByHttpClient(req, url);
    }

    public static String getOrPostByHttpClient(String url, boolean isHttpGet, Map<String, String> headerMap) {
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(6000).setSocketTimeout(6000).build();
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
        try {
            HttpPost httpPost = null;
            if (isHttpGet) {
                HttpGet httpGet = new HttpGet(url);
            } else {
                httpPost = new HttpPost(url);
            }
            httpPost.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
            httpPost.addHeader("Accept-Charset", "utf-8");
            httpPost.addHeader("Accept-Encoding", "gzip");
            httpPost.addHeader("Accept-Language", "en-US,en");
            if (null != headerMap && headerMap.size() > 0)
                for (Map.Entry<String, String> headerEntry : headerMap.entrySet()) {
                    String headerKey = headerEntry.getKey();
                    String headerValue = headerEntry.getValue();
                    httpPost.addHeader(headerKey, headerValue);
                }
            long startTime = System.currentTimeMillis();
            logger.debug("[HttpClient] START get url(" + url + ")");
            CloseableHttpResponse response = httpClient.execute((HttpUriRequest)httpPost);
            try {
                int statusCode = response.getStatusLine().getStatusCode();
                long endTime = System.currentTimeMillis();
                logger.debug("[HttpClient] END get url(" + url + ") elapse: " + ((endTime - startTime) / 1000L) + " s, result code: " + statusCode);
                if (statusCode >= 200 && statusCode < 500) {
                    String result = EntityUtils.toString(response.getEntity());
                    return result;
                }
            } finally {
                response.close();
            }
        } catch (Exception e) {
            logger.error("getOrPostByHttpClient 错误：" + e.getMessage());
            e.printStackTrace();
        } finally {}
        return "";
    }

    public static Connection.Response getByJsoup(String url) {
        return getByJsoup(url, Connection.Method.GET, null, null, null);
    }

    public static Connection.Response getByJsoup(String url, Connection.Method method) {
        return getByJsoup(url, method, null, null, null);
    }

    public static Connection.Response getByJsoup(String url, Connection.Method method, Map<String, String> headerMap, Map<String, String> dataMap, String requestBody) {
        try {
            Connection conn = Jsoup.connect(url).ignoreContentType(true).timeout(30000).method(method);
            if (null != headerMap && headerMap.size() > 0)
                conn = conn.headers(headerMap);
            if (null != dataMap && dataMap.size() > 0)
                conn = conn.data(dataMap);
            if (StringUtils.isNotBlank(requestBody))
                conn = conn.requestBody(requestBody);
            return conn.execute();
        } catch (Exception e) {
            logger.error("getByJsoup错误(" + e.getMessage() + ")，url=" + url + ", method=" + method + ", headerMap=" + headerMap + ", dataMap=" + dataMap + ", requestBody=" + requestBody);
            return null;
        }
    }

    public static String getByProxy(String proxyHost, int proxyPort, String userName, String passwd, String url) {
        CloseableHttpResponse httpResp = null;
        try {
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(1000).setSocketTimeout(5000).build();
            HttpClientBuilder clientBuilder = HttpClients.custom().setProxy(new HttpHost(proxyHost, proxyPort)).setDefaultRequestConfig(requestConfig);
            if (StringUtils.isNotBlank(userName) && StringUtils.isNotBlank(passwd)) {
                BasicCredentialsProvider basicCredentialsProvider = new BasicCredentialsProvider();
                basicCredentialsProvider.setCredentials(new AuthScope(proxyHost, proxyPort), (Credentials)new UsernamePasswordCredentials(userName, passwd));
                clientBuilder = clientBuilder.setDefaultCredentialsProvider((CredentialsProvider)basicCredentialsProvider);
            }
            CloseableHttpClient httpclient = clientBuilder.build();
            HttpGet httpGet = new HttpGet(url);
            httpResp = httpclient.execute((HttpUriRequest)httpGet);
            int statusCode = httpResp.getStatusLine().getStatusCode();
            if (statusCode == 200)
                System.out.println("成功");
            return EntityUtils.toString(httpResp.getEntity());
        } catch (Exception e) {
            return "";
        } finally {
            try {
                httpResp.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        String url = "http://httpbin.org/get";
        long start = System.currentTimeMillis();
        System.out.println(getByProxy("110.187.88.85", 20115, "godwin", "godwin", url));
        long end = System.currentTimeMillis();
        System.out.println("done. elapse: " + (end - start) + "ms.");
    }
}
